<template>
  <div class="raw-line-graph">
      <div ref="ele" class="canvas-parent" v-show="!!raw_input.extent">

      </div>
      <div v-show="!raw_input.extent" class="error-hints">
        <span>
              NO DATA
        </span>
      </div>      
  </div>
</template>

<script>
/* eslint-disable */
import echarts from "echarts";
import axios_default from "axios";
import randomcolor from "randomcolor";
import Debug from "debug";
const dbg = Debug("RawLineGraph.vue");
dbg.enabled = true;

export default {
  name: "RawLineOfAttribute",
  data() {
    return {
      raw_input: {
        extent: null,
        attributes: []
      },
      int_extent: [],
      line_points: [],
      lengthOfLinePoints: 0,
      abnormals: [],
      chart: echarts.init(document.createElement("span"))
    };
  },
  props: {
    good_feature_name_func: {
      type: Function
    },
    brush_color: {
      type: String
    }
  },
  mounted() {
    let chart = echarts.init(this.$refs["ele"]);
    this.chart = chart;
  },
  methods: {
    force_reset(){
      this.raw_input.extent = null;
      this.raw_input.attributes = [];
      this.int_extent = [];
      this.line_points=[];
      this.lengthOfLinePoints = 0;
      this.abnormals = []
    },
    drawByExtentAndAttr: async function(
      extent,
      attributes,
      lengthOfLinePoints
    ) {
      // debugger
      this.raw_input.extent = extent;
      this.raw_input.attributes = attributes;
      this.lengthOfLinePoints = lengthOfLinePoints;
      let int_extent = [Math.floor(extent[0]), Math.ceil(extent[1])].map(e =>
        parseInt(e)
      );
      this.int_extent = int_extent;
      this.chart.showLoading();
      let requests = attributes.map(attribute =>
        axios_default.get("/starter/feature/raw_line/", {
          params: {
            starterId: this.starterId,
            attr: attribute,
            extent: int_extent
          }
        })
      );
      let resps = await Promise.all(requests);
      let points = resps.map(resp => resp.data["points"]);
      // debugger;
      let abnormals = resps[0].data["abnormals"];
      this.line_points = points;
      this.abnormals = abnormals;
      this.chart.hideLoading();
    }
  },
  computed: {
    starterId() {
      return this.$store.state.starterId;
    },
    abnormal_type2color() {
      return this.$store.state.abnormal_type2color;
    },
    trend_colors() {
      return this.$store.state.trend_colors;
    },
    highlight_testids() {
      return this.$store.state.highlight_testids;
    },
    abnormal_type2comment() {
      return this.$store.getters["abnormal_type2comment"];
    },
    gray_colors() {
      return this.$store.state["gray_colors"];
    },
    font_size() {
      return this.$store.getters["axis_font_size"];
    },
    func_orderOfMagnitude() {
      return function convertOrderOfMagnitude(n) {
        var order = Math.floor(Math.log(n) / Math.LN10 + 0.000000001); // because float math sucks like that
        return Math.pow(10, order);
      };
    },
    MIN_MAX_ORDER() {
      return this.line_points.map((line_arr, line_i) => {
        let min = _.min(line_arr.map(e => e["value"]));
        let max = _.max(line_arr.map(e => e["value"]));
        return {
          min: min,
          max: max,
          order: this.func_orderOfMagnitude(max - min)
        };
      });
    },
    opt_abnormal_series() {
      let vue = this;
      let groups = {};
      for (let o of this.abnormals) {
        let abnormal_type = o.abnormal_type;
        if (!groups[abnormal_type]) {
          groups[abnormal_type] = [];
        }
        groups[abnormal_type].push(o);
      }
      return _.map(groups, (o_arr, abnormal_type) => {
        return {
          type: "custom",
          name: abnormal_type,
          xAxisIndex: 0,
          yAxisIndex: 0,
          itemStyle: {
            color: (() => {
              return this.abnormal_type2color[
                this.abnormal_type2comment[abnormal_type]
              ];
            })(),
            emphasis: {
              borderWidth: 1,
              shadowBlur: 10,
              shadowOffsetX: 0,
              shadowOffsetY: 0,
              shadowColor: "rgba(0,0,0,0.5)"
            }
          },
          data: o_arr.map(e => [e.test_id, 0, e.abnormal_type]),
          renderItem: function renderRectInRaw(params, api) {
            // console.info({params,api})
            // debugger
            let test_id = api.value(0);
            let type = api.value(2);
            let sized = api.size([test_id, 0]);
            let coorded = api.coord([test_id, 0]);
            const RECT_HEIGHT = 20;
            let sized11 = api.size([1, 1]);
            let coord00 = api.coord([0, 0]);
            return {
              type: "rect",
              shape: echarts.graphic.clipRectByRect(
                {
                  height: params.coordSys.height,
                  y: params.coordSys.y,
                  x: coorded[0] - sized11[0] / 2,
                  width: sized11[0]
                },
                {
                  x: params.coordSys.x,
                  y: params.coordSys.y,
                  width: params.coordSys.width,
                  height: params.coordSys.height
                }
              ),
              style: (() => {
                if (vue.highlight_testids.includes(test_id)) {
                  return {
                    fill: api.style()["fill"],
                    stroke: "white",
                    shadowBlur: 10,
                    shadowOffsetX: 0,
                    shadowOffsetY: 0,
                    shadowColor: "red"
                  };
                } else {
                  return {
                    fill: api.style()["fill"]
                  };
                }
              })()
            };
          }
        };
      });
    },
    opt_line_series() {
      return this.line_points.map((points, i) => {
        return {
          name: this.raw_input.attributes[i],
          type: "line",
          data: points.map(e => [e.test_id, e.value]),
          lineStyle: {
            color: this.trend_colors[i],
            shadowColor: "white",
            shadowBlur: 5
          },
          itemStyle: {
            color: this.trend_colors[i],
            shadowColor: "white",
            shadowBlur: 5
          },
          symbol: i % 2 ? "rect" : "triangle",
          showSymbol: true,
          symbolSize: 10,
          smooth: true,
          yAxisIndex: i,
          xAxisIndex: 0
        };
      });
    },
    opt_yAxis() {
      return this.raw_input.attributes
        .map((attr, i) => {
          return {
            name: this.good_feature_name_func(attr),
            nameGap: 60,
            nameRotate: 90,
            nameLocation: "center",
            nameTextStyle: {
              color: this.trend_colors[i],
              shadowColor: "red",
              shadowBlur: 1,
              fontSize: this.font_size,
              rich: {
                name: {
                  align: "center"
                }
              }
            },
            min: ($ => {
              let min_max = this.MIN_MAX_ORDER[i];
              try {
                let order = min_max.order;
                return order * (Math.ceil(min_max.min / order) - 1);
              } catch (e) {
                return null;
              }
            })(),
            max: ($ => {
              let min_max = this.MIN_MAX_ORDER[i];
              try {
                let order = min_max.order;
                return order * (Math.ceil(min_max.max / order) + 1);
              } catch (e) {
                return null;
              }
            })(),
            gridIndex: 0,
            splitLine: {
              show: false
            },
            axisLine: {
              onZero: false,
              lineStyle: {
                color: this.gray_colors[0]
              }
            },
            axisPointer: {
              type: "shadow",
              show: false
            },
            axisLabel: {
              inside: false,
              color: this.gray_colors[1],
              fontSize: this.font_size
            }
          };
        })
        .concat([
          {
            name: "y-1/2",
            gridIndex: 1,
            show: false
          }
        ]);
    },
    opt_xAxis() {
      return [
        {
          type: "value",
          scale: true,
          axisLine: {
            onZero: false,
            lineStyle: {
              fontSize: 12,
              color: this.gray_colors[0]
            }
          },
          splitLine: {
            show: false
          },
          name: "Test No.",
          nameGap: 34,
          gridIndex: 0,
          nameLocation: "center",
          nameTextStyle: {
            color: this.gray_colors[1],
            textShadowColor: "transparent",
            textShadowBlur: 0,
            textShadowOffsetY: 14,
            fontSize: this.font_size
          },
          axisLabel: {
            color: this.gray_colors[1],
            fontSize: this.font_size,
            formatter: function(value, index) {
              return parseInt(Math.ceil(value));
            }
          }
        },
        {
          type: "category",
          gridIndex: 1,
          data: _.range(0, this.lengthOfLinePoints),
          show: false
          // min:0,
          // max:100
        }
      ];
    },
    opt_Echelon() {
      let vue = this;
      if (vue.int_extent.length == 2) {
        return {
          name: "",
          type: "custom",
          data: [0],
          xAxisIndex: 1,
          yAxisIndex: vue.opt_yAxis.length - 1,
          renderItem: function renderEchelon(params, api) {
            if (api.coord) {
              // debugger
              let x1 = api.coord([vue.int_extent[0], 0])[0];
              let x2 = api.coord([vue.int_extent[1], 0])[0];
              return {
                type: "polygon",
                shape: {
                  points: [
                    [x1, params.coordSys.y],
                    [x2, params.coordSys.y],
                    [
                      params.coordSys.x + params.coordSys.width,
                      params.coordSys.y + params.coordSys.height
                    ],
                    [
                      params.coordSys.x,
                      params.coordSys.y + params.coordSys.height
                    ]
                  ]
                },
                style: {
                  fill: vue.brush_color,
                  stroke: "rgba(120,140,180,0.8)",
                  lineWidth: 1
                }
              };
            } else {
              ("no api.coord??");
              debugger;
            }
          }
        };
      } else {
        return null;
      }
    },
    opt_grid() {
      return [
        {
          left: 100,
          right: 100,
          top: 10,
          bottom: 60,
          show: true,
          backgroundColor: this.brush_color ,//"rgba(120,140,180,0.3)",
          borderColor: "white"
        },
        {
          left: 100,
          right: 100,
          top: 0 - 60,
          height: 10 + 60,
          show: false
        }
      ];
    },
    echarts_options() {
      let vue = this;
      return {
        series: [...vue.opt_line_series].concat([
          // ...vue.opt_abnormal_series,
          vue.opt_Echelon
        ]),
        // legend: {
        //   bottom: 10,
        //   formatter: function(param) {
        //     if (Number.isNaN(Number(param))) {
        //       return param;
        //     } else {
        //       return `${vue.abnormal_type2comment[param]}`;
        //     }
        //   },
        //   data: [
        //     ...this.opt_abnormal_series.map(e => e.name),
        //     ...this.opt_line_series.map(e => e.name)
        //   ] //强行更新,避免legend的不一致
        // },
        tooltip: {
          trigger: "axis",
          formatter: function(params, ticket, callback) {
            // debugger;
            let test_id = params[0].axisValue;
            let attr_name_and_value = params
              .filter(p => p.seriesType == "line")
              .map(p => {
                let value = String(p.data[1]);
                let dot = value.indexOf(".");
                if (dot && value.length - dot > 3) {
                  value = Number(value).toFixed(3);
                }
                return `${vue.good_feature_name_func(p.seriesName)} : ${value}`;
              })
              .join("<br>");
            let tip = `Test No. : ${test_id}<br>` + attr_name_and_value;
            let find_abnormal_record = vue.abnormals.find(
              e => e.test_id == test_id
            );
            if (find_abnormal_record) {
              // tip += `<br>type : ${find_abnormal_record.abnormal_type}`;
            }
            return tip;
          },
          extraCssText: "text-align: left;"
        },
        grid: this.opt_grid,
        dataZoom: {
          type: "inside",
          top: 210,
          height: 30,
          startValue: vue.raw_input.extent ? vue.raw_input.extent[0] : null,
          endValue: vue.raw_input.extent ? vue.raw_input.extent[0] + 100 : null
        },
        xAxis: this.opt_xAxis,
        yAxis: this.opt_yAxis,
        graphic: {
          type: "text",
          left: "center",
          top: "middle",
          style: {
            text:
              " " ||
              `${vue.raw_input.attributes.join("&")}[${vue.int_extent[0]},${
                vue.int_extent[1]
              }]`,
            font: "bolder 30px 'Avenir', Helvetica, Arial, sans-serif",
            fill: "rgba(0,0,0,0.2)"
          }
        }
      };
    },
    DEBUG_getOptions() {
      let s = this.echarts_options;
      return this.chart.getOption();
    }
  },
  watch: {
    echarts_options: function(val) {
      try {
        this.chart.clear();
        this.chart.setOption(val);
      } catch (EchartsBug) {}
    },
    starterId() {
      this.raw_input.extent = null;
      this.raw_input.attributes = [];
      this.int_extent = [];
      this.line_points = [];
      this.abnormals = [];
    }
  }
};
</script>

<style lang="scss">
.raw-line-graph {
  $height: 234px;
  width: 1311px;
  height: $height;
  position: relative;
  .canvas-parent {
    height: $height;
    width: 1311px;
  }
  .error-hints {
    font-size: 50px;
    color: #f7f7f7;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    text-shadow: 1px 1px 2px black;
  }
}
</style>
